/**
 * 
 */
package us.mmapp;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import us.mmapp.SearchManager.PredicateType;
import us.mmapp.entities.ObjectEntity;
import us.mmapp.interfaces.OnApplicationDataChangeListener;
import us.mmapp.util.ApplicationData;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.Preference;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ZoomButtonsController.OnZoomListener;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

/**
 * @author vlady
 *
 */
public class OnMapActivity extends MapActivity implements OnApplicationDataChangeListener {

	public static final int FILTER_REQUEST_CODE = 1;
	public static final int SEARCH_REQUEST_CODE = 2;
	public static ArrayList<ObjectEntity> lastCluster;
	private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
	private PinchMapView mMapView;
	private ClusterManager mCManager;
	private ArrayList<ObjectEntity> mObjects;
	private String mUserName;
	private String mPassword;
	/* (non-Javadoc)
	 * @see com.google.android.maps.MapActivity#isRouteDisplayed()
	 */
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	@Override
	public void onPause()
	{
		super.onPause();
		ApplicationData.deattach(this);
	}
	@Override
	public void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    
	    setContentView(R.layout.on_map_layout);
	    
		SharedPreferences settings = getSharedPreferences("LOGIN", 0);
		boolean isLoggedIn = settings.getBoolean("loggedIn", false);

		if (!isLoggedIn)
		{
			startActivity(new Intent(this, LoginActivity.class));
			return;
		}
		mUserName = settings.getString("username", "");
		mPassword = settings.getString("password", "");
	    
	    mMapView = (PinchMapView) findViewById(R.id.mapview);
	    mMapView.addClass(this);
	    mMapView.setBuiltInZoomControls(true);
	    //
	    mMapView.setSatellite(true);
	    mMapView.getZoomButtonsController().setOnZoomListener( new OnZoomListener() {
			
			public void onZoom(boolean zoomIn)
			{
				if (zoomIn && mMapView.getZoomLevel() < 21)
					mMapView.getController().zoomIn();
				if (!zoomIn)
					mMapView.getController().zoomOut();
				//Log.e("SPAN", mMapView.getLatitudeSpan() + " " + mMapView.getLongitudeSpan());
				updateMapWithCluster();
			}
			
			public void onVisibilityChanged(boolean visible) {
				// TODO Auto-generated method stub
				
			}
		});
	    doFetch();
	}
	@Override
	public void onResume()
	{
		super.onResume();
		mMapView = (PinchMapView) findViewById(R.id.mapview);
		ApplicationData.attach(this);
	}
	/**
	 *  Fetch for all objects.
	 */
	void doFetch()
	{
		mObjects = ApplicationData.getObjects();
		updateObjects(mObjects);
	}
	void manageFetch(JSONObject result)
	{
		JSONArray resultArray = null;
		try
		{
			resultArray = result.getJSONArray("result");
		} catch (JSONException e) {}
		
		if (resultArray == null)
			return;
		//resultArray JSONARRAY
		
		mObjects = new ArrayList<ObjectEntity>();
		for (int i = 0; i < resultArray.length(); ++i)
		{
			JSONObject obj = null;
			try
			{
				obj = resultArray.getJSONObject(i);
				mObjects.add(new ObjectEntity(obj));
			} catch (JSONException e) {}
			if (obj == null)
				continue;
			
		}
		updateObjects(mObjects);
	}
	private void updateObjects(ArrayList<ObjectEntity> objects)
	{
		if (objects == null)
			return;
		Log.e("OFF: ", "Aici: " + objects.size());
		mCManager = new ClusterManager(OnMapActivity.this, objects, mMapView);

		// Start working on them -> clusters
		if (objects.size() > 0)
			for (int i = 0; i < mCManager.K; ++i)
			{
				makeWorker(i);
			}
		else
			mMapView.getOverlays().clear();
	}
	private void makeWorker(int i)
	{
		//parameters, the progress values, and the final value of the task,
		AsyncTask<Integer, Void, Integer> t = new AsyncTask<Integer, Void, Integer>() {
			@Override
			protected Integer doInBackground(Integer... params)
			{
				mCManager.prepareCluster(params[0]);
				return params[0];
			}
			@Override
			protected void onPostExecute(Integer result)
			{
				updateMapWithCluster(result);
			}
		};
		// Args needed for the working thread.
		Integer[] args = {i};
		Log.e("CLUSTERS", "Starting work for: " + i);
		t.execute(args);
	}
	public synchronized void updateMapWithCluster()
	{
		if (mCManager != null)
		{
			int cluster = mCManager.whichCluster(mMapView.getZoomLevel());
			updateMapWithCluster(cluster);
		}
	}
	private synchronized void updateMapWithCluster(int idx)
	{
		if (mCManager == null)
			return;
		Log.e("CLUSTERS", "Done work for: " + idx);
		int zoomLevel = mMapView.getZoomLevel();
		
		List<Overlay> mapOverlays = mMapView.getOverlays();
		
		// Find best zoom overlay available
		int best = -1;
		for (int i = 0; i <= zoomLevel; ++i) if (mCManager.ready[mCManager.whichCluster(i)] != 0) best = mCManager.whichCluster(i);
		if (best != -1)
		{
			mapOverlays.clear();
			mapOverlays.add(mCManager.clustersOverlays[best]);
			mMapView.postInvalidate();
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.menu, menu);
	    return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem menu){
		switch (menu.getItemId())
		{
			case R.id.filter_menu: this.startActivityForResult(new Intent(OnMapActivity.this, FilterActivity.class), FILTER_REQUEST_CODE); break;
			case R.id.search_menu:
				this.startActivityForResult(new Intent(OnMapActivity.this, SearchActivity.class), SEARCH_REQUEST_CODE); break;
			default: break;
			
		}
		return true;
	}
	
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FILTER_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
            	
            	
            	//Start filtering
            	int[] selected=data.getIntArrayExtra("type");
            	String[] keywords=data.getStringArrayExtra("keyword");
            	ArrayList<ObjectEntity> filteredResult=mObjects;
            	for(int i=0; i<selected.length; i++)
            	{
            		PredicateType type;
            		switch (selected[i])
            		{
            			case 0: type = PredicateType.Title; break;
            			case 1: type = PredicateType.Description; break;
            			case 2: type = PredicateType.Tags; break;
            			case 3: type = PredicateType.Comment; break;
            			case 4: type = PredicateType.Friend; break;
            			default: type = PredicateType.Any; break;
            		}
            		SearchManager manager=new SearchManager(filteredResult);
            		filteredResult=manager.search(type, keywords[i], true, true);
            	}
        		
        		updateObjects(filteredResult);
        		
            }
            else
            {
            	updateObjects(mObjects);
            }
        }
        else if (requestCode == SEARCH_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
            	int latitude = data.getIntExtra("latitude", 0);
            	int longitude = data.getIntExtra("longitude", 0);
            	GeoPoint point = new GeoPoint(latitude, longitude);
            	MapController controller = mMapView.getController();
            	controller.animateTo(point);
            	if (mMapView.getZoomLevel() != 18)
            	{
            		controller.setZoom(18);
            		this.updateMapWithCluster();
            	}
            }
        }
    }
	@Override
	public void onApplicationDataChange()
	{
		mObjects = ApplicationData.getObjects();
		updateObjects(mObjects);
	}
	
}
